<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>性能优化</title>
</head>
<body>
<!-- 

性能优化：核心就是减小资源从服务器下载到客户端的延迟

    参考文章：https://blog.csdn.net/daimomo000/article/details/72897436

    1. 减少http请求：
        （1）合理配置http缓存
            * 强缓存： 设置缓存时间，max-age，有效时间内浏览器直接走缓存，超过有效时间后走协商缓存
            * 协商缓存： 服务器在响应头中配置 last-modified(文件最后一次修改时间) 和 e-tag(文件标识)，
                        浏览器将这两个字段带在请求头中，服务器去对比这两个字段，
                        是一致说明文件未修改，返回 304 状态码，代表让浏览器走缓存；
                        不一致说明修改了，返回 200 状态码，返回最新的资源给浏览器。                        

        （2）css精灵图
            * 合并css图片，将多个小图标放在一张图片上，只用请求这一张图片
        （3）资源合并与压缩
            * 如果可以的话，尽可能将外部的脚本、样式进行合并，多个合为一个。另外，css、js、image都能用相应的工具压缩，
              压缩后能省下不少空间。
        （4）inline image
            * 使用 data：url scheme 的方式将图片嵌入到页面或css中，base64的图片格式不用发请求，但会增加页面的体积，
              所以体积小图片可以用这种方式，体积大的可能会得不偿失。
        （5）图片懒加载
            * 实际上不能减少http请求数，但是能在某些条件下或页面刚加载时减少请求数。对于图片而言，在页面刚加载的时候只加载第一屏，
              当用户继续往后滚屏的时候才加载后续的图片。如果用户只对第一屏内容感兴趣，后面的图片就都不用加载了。
    2. 将外部脚本置底、异步执行inline脚本
        * 核心就是保证脚本在页面内容后面加载 
        * 外链脚本加载时会阻塞其他资源，例如在加载外链脚本完成之前，它后面的图片、样式以及其他脚本都处于阻塞状态，直到脚本加载完成才会开始加载。
        * 最简单的方式就是将脚本尽可能的往后挪；
        * 异步执行：使用script标签的defer属性、setTimeout、web worker
    3. 懒加载js
        * 只在需要的时候加载，一般情况下并不加载信息内容
    4. 将css放在head中
        * 将css放body中，浏览器可能还未下载和解析到css就开始渲染页面了，这就导致页面从无css状态跳转到css状态，体验不好。
        * 有些浏览器会等到css下载完才开始渲染页面，如果css放靠下面的位置会导致浏览器将渲染时间推迟。
    5. 代码级优化
        > js
            （1）DOM
                a. 减少重排(回流)和重绘
                b. HTML Collection：html收集器，在脚本中document.images、getElementsByTagName()获取的都是HTMLCollection类型的集合，
                   使用时大多作为数组使用，不过在访问性能上比数组要差很多，每次访问集合都会重新执行这个查询并更新结果。如果是遍历时，建议将length属性先用变量存起来。
            （2）减少作用域链查找
                * 在循环中尤其要注意这个问题，如果在循环中需要访问非本作用域的变量，请在遍历之前用局部变量缓存该变量，并在遍历结束后重写那个变量。
                  这一点对于全局变量来说很重要，全局变量处于作用域链最顶端，访问次数是最多的。
            （3）数据访问
                * js中对于直接量和局部变量的访问是最快的，对对象属性和数组的访问需要更大的开销。减少对对象和数组的深度访问。
                * 当出现以下情形时，建议将数据放入局部变量：
                    * 对任何对象的属性访问超过一次
                    * 对任何数组成员的访问超过一次
            （4）字符串拼接
                * 在js中用“+”拼接字符串的方式效率是比较低的，因为每次运行都会开辟新的内存并生成新的字符串变量，然后将拼接结果赋值给新变量。
                与之相比更高效的是利用数组的join方法，将要拼接的字符串都放入数组中并调用其join方法得到结果，不过数组也要一定的开销。
                所以当要拼接的字符串比较多时可以考虑此方法        
        > css选择符
            * 浏览器对css选择符的解析是从右往左进行的，在写选择符的需要注意一些事项。
              比如 #head div{}，浏览器必须先遍历查找div的所有祖先节点，这样效率就会低很多。
-->

<!-- 
    
webpack性能优化
    具体参考：https://www.jianshu.com/p/809958a504b8

    1. 减少webpack打包时间
        （1）优化loader
            * 对于loader，影响打包效率的是它的属性Babel。Babel会将代码转换为字符串生成AST，然后对AST继续进行转变最后生成新代码，项目越大，转换代码越多，效率越低。
            * 优化Loader的文件搜索范围。比如配置只在src文件下查找，不去查找node-modules
            * 把Babel编译过的文件缓存起来。下次只需要编译更改过的代码文件即可
        （2）HappyPack
            * 可以将Loader的同步执行转换为多线程的
        （3）DllPlugin
            * 可以将特定的类库提前打包然后引入。这种方式可以极大的减少打包类库的次数，只有当类库更新版本才有需要重新打包，并且也实现了将公共代码抽离成单独文件的优化方案。
    2. 减少webpack打包后的文件体积
        （1）按需加载
            * 如果把十几个页面甚至更多的路由页面全部打包进一个js文件的话，虽然将多个请求合并了，但是同样也加载了很多并不需要的代码，耗费了更长时间。
              为了将首页能更快呈现，这时候可以使用按需加载，将每个路由单独打包成一个文件，当然不仅路由可以按需加载，对于lodash这种大型类库也可以使用这个功能。
            * 方法：当使用的时候再去下载对应文件，返回一个Promise当Promise成功以后去执行回调
        （2）Scope Hoisting
            Scope Hoisting会分析出模块之间的依赖关系，尽可能的把打包出来的模块合并到一个函数中去。
        （3）Tree Shaking
            * 可以实现删除项目中未被引用的代码，像一些冗余代码，或者是lodash里有很多没有使用的方法。
              webpack4，开启生产环境会自动启动这个优化功能。
        （4）图片压缩以及转化成base64格式
            * 可以在url-loader中设置limit，小于limit的图片将转化成base64格式
            * 比较大的图片可以用 image-webpack-loader 来压缩图片
        （5）productionSourceMap: false
            * map文件的作用：项目打包后，代码都是经过压缩加密的，如果运行时报错，输出的错误信息无法得知是哪里的代码报错。
                           有了map文件就可以像未加密的代码一样，准确的输出是哪一行哪一列有错。

 -->
</body>
</html>